package com.tuoyu.peopletest.view.ac;

import static com.tuoyu.peopletest.common.MyApplication.context;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.TimeUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.blankj.utilcode.util.KeyboardUtils;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

import com.stresscube.stresscubetest.ScanTest;
import com.stresscube.stresscubetest.TestCallback;
import com.stresscube.usbdevice.USBDevicePDHIDWithAddress;
import com.stresscube.usbdevice.data.ParaName;
import com.stresscube.usbdevice.data.ParaScan;
import com.stresscube.usbdevice.utils.WorkMessage;
import com.tuoyu.peopletest.R;
import com.tuoyu.peopletest.common.Constant;
import com.tuoyu.peopletest.entity.DataBean;
import com.tuoyu.peopletest.utils.DeviceUtils;
import com.tuoyu.peopletest.utils.SCTimeUtils;
import com.tuoyu.peopletest.utils.SettingsClass;
import com.tuoyu.peopletest.utils.Utils;
import com.tuoyu.peopletest.utils.WebApi;

import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class MainActivity extends NomalBaseActivity implements TestCallback {
    String mstrServerIP = "https://data.stressonline.cn:8445/";
    static final String TAG = "Main";
    static final byte testColor = 0x40; //测试使用的颜色， 15为波长365，40为波长470

    Button mBtn670, mBtn365, mBtn470, mBtn525_1, mBtn525_2, mBtn525All;
    Button mBtnLEDClicked; //当前点亮的LED灯
    Button mBtn364, mBtn470_2, mBtn525_3, mBtnLEDOn_2;
    EditText mEdtADGain;
    EditText mEdtStart;
    EditText mEdtStop;
    EditText mEdtStep;
    SeekBar mSBBrightness;
    CheckBox mcbColor1, mcbColor2, mcbColor3, mcbColor4, mcbColor5, mcbColor6;
    CheckBox mcbLaserScan;
    RadioGroup mrgP1LED, mrgADPosition;
    //    USBDeviceHID mScanTest.getDevice() = new USBDeviceHID();
//    USBDevicePDHIDWithAddress mScanTest.getDevice() = new USBDevicePDHIDWithAddress();
    LineChart mLineChart;   //显示曲线
    TextView mtvResult; //结果显示
    //    byte position = 2, color = 1; //孔位为2，颜色为1
//    byte ledPosition = (byte)0xF1, color = 0x0c; //孔位为2，颜色为1
    byte ledPosition = (byte) 0x03, color = (byte) 0xff; //孔位为3，颜色为全亮
    byte normal_speed = 10, high_speed = 1;//新版为变速，使用1， 旧版激光扫描使用0，无变速
    byte adPosition = (byte) 0x01;
    byte adAMSPosition=(byte)0x02, adAMSGain=(byte)0x01;
    boolean mbLED470Clicked = false;
    //    byte adPosition = 2; //孔位为2，颜色为1
    //    ArrayList<ArrayList<Integer>> mListResult = new ArrayList<ArrayList<Integer>>(); //保存读出来的波长数据，一次10个波长
    ArrayList<Integer> mListResult = new ArrayList<>(); //保存读出来的数据
    boolean[] bF8ClearNIR = new boolean[]{true, true, true, true, true, true, true, true, true, true}; //是否选择各个波长
//    String[] mstrWaveLength = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "clear", "NIR"};

    int mStart, mStop, mStep; //起始位置、终止位置、每步几个点（最少1个点，此时采样频率为50Hz，为2时，采样频率为100Hz）
    private EditText etNumber;
    private String mArea1;
    private String mArea2;
    private String waveLength;
    private EditText etProject;

    //    final int MAX_PEAK = 550 * 1000;
    final int MAX_PEAK = 750 * 10000;
    byte gain = 0x0f, amplify = 43;

    ScanTest mScanTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


//        findViewById(R.id.tv_save).setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                mArea1 = 23.456+"";
//                mArea2 = 56.2313+"";
//                saveData();
//
//            }
//        });
    }

    @Override
    public void initContentView() {
        setContentView(R.layout.activity_main);

        InitData();
    }

    @Override
    public void initChildView() {

    }

    @Override
    protected void onStart() {
        Log.d("","onStart");
        super.onStart();
//        mScanTest.getDevice().init(this);
        mScanTest.init();
    }

    @Override
    protected void onStop() {
        Log.d("","onStop");
        super.onStop();
//        mScanTest.getDevice().release();
        mScanTest.release();
    }

    void InitData() {
        etNumber = findViewById(R.id.et_input);
        mBtn670 = findViewById(R.id.btn670);
        mBtn365 = findViewById(R.id.btn365);
        mBtn470 = findViewById(R.id.btn470);
        mBtn525_1 = findViewById(R.id.btn525_1);
        mBtn525_2 = findViewById(R.id.btn525_2);
        mBtn525All = findViewById(R.id.btn525All);

        mBtn364 = findViewById(R.id.btn364);
        mBtn470_2 = findViewById(R.id.btn470_2);
        mBtn525_3 = findViewById(R.id.btn525_3);
        mBtnLEDOn_2 = findViewById(R.id.btnLEDOn_2);
        ResetBtnClicked();

        mEdtADGain = findViewById(R.id.edtADGain);
        mEdtStart = findViewById(R.id.edtStart);
        mEdtStop = findViewById(R.id.edtStop);
        mEdtStep = findViewById(R.id.edtStep);

        mtvResult = findViewById(R.id.tvResult);
        mLineChart = findViewById(R.id.lineChart_01);
        mSBBrightness = findViewById(R.id.sbBrightness);
        mSBBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                ((TextView) findViewById(R.id.tvBrightness)).setText(String.valueOf(progress));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
//        for (int i = 0; i < 10; i++)
//            mListResult.add(new ArrayList<>());
        mListResult.clear();
        mcbColor1 = findViewById(R.id.cbLight1);
        mcbColor2 = findViewById(R.id.cbLight2);
        mcbColor3 = findViewById(R.id.cbLight3);
        mcbColor4 = findViewById(R.id.cbLight4);
        mcbColor5 = findViewById(R.id.cbLight5);
        mcbColor6 = findViewById(R.id.cbLight6);

        mrgP1LED = findViewById(R.id.rgP1LED);
        mrgP1LED.setOnCheckedChangeListener((group, checkedId) -> openP1LED(checkedId));

        mcbLaserScan = findViewById(R.id.cbLaser);
        mcbLaserScan.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                ledPosition = 1;
                normal_speed = 2;
//                normal_speed=0; high_speed=0;
            } else {
                ledPosition = 3;
                normal_speed = 10;
//                normal_speed=1; high_speed=10;
            }
        });

        mrgADPosition = findViewById(R.id.rgADPosition);
        mrgADPosition.setOnCheckedChangeListener((group, checkedId) -> {
            getADPosition(checkedId);
        });

        SettingsClass.getSettings();
        mSBBrightness.setProgress(SettingsClass.getMainBrightness());
        mEdtStart.setText(SettingsClass.getMainStart() + "");
        mEdtStop.setText(SettingsClass.getMainStop() + "");
        if (SettingsClass.getMainPeak())
            ((RadioGroup) findViewById(R.id.rgPeakOrValley)).check(R.id.rbPeakOrValley_Peak);
        else
            ((RadioGroup) findViewById(R.id.rgPeakOrValley)).check(R.id.rbPeakOrValley_Valley);
        if (SettingsClass.getMainADPosition() == 1)
            ((RadioGroup) findViewById(R.id.rgADPosition)).check(R.id.rbADPosition1);
        else
            ((RadioGroup) findViewById(R.id.rgADPosition)).check(R.id.rbADPosition2);

        mScanTest=new ScanTest(this, this);
    }

    //打开孔1的LED灯，或者孔1关灯
    private void openP1LED(int checkedId) {
        if (checkedId == R.id.rbP1LEDOff) {
            p1LEDOff();
            return;
        }
        byte color = 0x00;
        if (checkedId == R.id.rbP1LED1)
            color = 0x01;
        else if (checkedId == R.id.rbP1LED2)
            color = 0x02;
        else if (checkedId == R.id.rbP1LED3)
            color = 0x04;
        else if (checkedId == R.id.rbP1LED4)
            color = 0x08;
        else if (checkedId == R.id.rbP1LED5)
            color = 0x10;
        else if (checkedId == R.id.rbP1LED6)
            color = 0x20;
        else if (checkedId == R.id.rbP1LED7)
            color = 0x40;
        else if (checkedId == R.id.rbP1LED8)
            color = (byte) 0x80;
        else if (checkedId == R.id.rbP1LEDLaser)
            color = (byte) 0xa1;

//        ledPosition = 0x01;
        int brightness = mSBBrightness.getProgress();
        if (!mScanTest.getDevice().LEDOn(ledPosition, color, brightness))
            DisplayMessage("孔1开灯失败");
        else
            DisplayMessage("孔1开灯成功");
    }

    private void p1LEDOff() {
        boolean bSuccess;
        bSuccess = mScanTest.getDevice().LEDOn((byte) 0x01, (byte) 0x00, 0);
        if (!mScanTest.getDevice().LEDOn((byte) 0x01, (byte) 0xa0, 0) || !bSuccess)
            DisplayMessage("孔1关灯失败");
        else
            DisplayMessage("孔1关灯成功");
//        ledPosition = 0x03;
    }

    public void DisplayMessage(String msg) {
        Log.d(TAG, msg);
        msg += "\r\n" + mtvResult.getText();
        mtvResult.setText(msg);
    }

    public void DisplayAreaMessage(String msg) {
        ((TextView) findViewById(R.id.tvResultArea)).setText(msg);
        Log.d(TAG, msg);
    }

    public void DisplayAverageMessage(String msg) {
        ((TextView) findViewById(R.id.tvResultAverage)).setText(msg);
        Log.d(TAG, msg);
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnAdd: {
                int progress = mSBBrightness.getProgress();
                progress++;
                if (progress > 800) progress = 800;
                mSBBrightness.setProgress(progress);
                break;
            }
            case R.id.btnSub: {
                int progress = mSBBrightness.getProgress();
                progress--;
                if (progress < 0) progress = 0;
                mSBBrightness.setProgress(progress);
                break;
            }
            case R.id.btnLEDOn:
                LEDOn();
                break;
            case R.id.btnLEDOff:
                LEDOff();
                break;
            case R.id.btnHome:
                Home();
                break;
            case R.id.btnTrayOut:
                TrayOut();
                break;
            case R.id.btnTrayIn:
                TrayIn();
                break;
            case R.id.btnTrayMoveStart:
                TrayMoveStart();
//                test();
                break;
            case R.id.btnTrayMoveEnd:
                TrayMoveEnd();
                break;
            case R.id.btnScanRead:
                ScanRead();
                break;
            case R.id.btnScanReadAMS:
                ScanReadAMS();
                break;
            case R.id.btnScanReadNoMove:
                ScanReadNoMove();
                break;
            case R.id.btnScanRead10:
                ScanRead10();
                break;
            case R.id.btnCalibrateBrightness:
                calibrateBrightness();
                break;
            case R.id.btnScanReadAfterCalibrateBrightness:
                scanReadAfterCalibrateBrightness();
                break;
//            case R.id.btnMainTest:
//                Intent mainTestIntent = new Intent(this, MainActivityTest.class);
//                startActivity(mainTestIntent);
//                finish();
//                break;
            case R.id.btnStart:
                Intent startIntent = new Intent(this, StartActivity.class);
                startActivity(startIntent);
                finish();
                break;
//            case R.id.btnMainStandardTest:
//                Intent mainStandardTestIntent = new Intent(this, MainActivityStandardTest.class);
//                startActivity(mainStandardTestIntent);
//                finish();
//                break;
            case R.id.btnRead:
                Read();
                break;
            case R.id.cbF1:
                ClickF8ClearNIR(1);
                break;
            case R.id.cbF2:
                ClickF8ClearNIR(2);
                break;
            case R.id.cbF3:
                ClickF8ClearNIR(3);
                break;
            case R.id.cbF4:
                ClickF8ClearNIR(4);
                break;
            case R.id.cbF5:
                ClickF8ClearNIR(5);
                break;
            case R.id.cbF6:
                ClickF8ClearNIR(6);
                break;
            case R.id.cbF7:
                ClickF8ClearNIR(7);
                break;
            case R.id.cbF8:
                ClickF8ClearNIR(8);
                break;
            case R.id.cbClear:
                ClickF8ClearNIR(9);
                break;
            case R.id.cbNIR:
                ClickF8ClearNIR(10);
                break;
            case R.id.cbLight1:
            case R.id.cbLight2:
            case R.id.cbLight3:
            case R.id.cbLight4:
            case R.id.cbLight5:
            case R.id.cbLight6:
                SetColor();
                break;
            case R.id.btn365:
                OpenLED365();
                waveLength = mBtn365.getText().toString().trim();
                break;
            case R.id.btn670:
                OpenLED670();
                waveLength = mBtn670.getText().toString().trim();
                break;
            case R.id.btn470:
                OpenLED470();
                waveLength = mBtn470.getText().toString().trim();
                break;
            case R.id.btn525_1:
                OpenLED525_1();
                waveLength = mBtn525_1.getText().toString().trim();
                break;
            case R.id.btn525_2:
                OpenLED525_2();
                waveLength = mBtn525_2.getText().toString().trim();
                break;
            case R.id.btn525All:
                OpenLED525All();
                waveLength = mBtn525All.getText().toString().trim();
                break;
            case R.id.cbColor470_1:
            case R.id.cbColor470_2:
            case R.id.cbColor470_3:
                SetColor470();
                break;
            case R.id.btnReadCalibration:
                ReadCalibrateDataFromDevice12_02();
                break;

            case R.id.btn364:
                OpenLED364();
                break;
            case R.id.btn470_2:
                OpenLED470_2();
                break;
            case R.id.btn525_3:
                OpenLED525_3();
                break;
            case R.id.btnLEDOn_2:
                OpenLED_2();
                break;
        }
    }

    //亮度校准，amplify从50向下，直到最高值小于600000
    void calibrateBrightness() {
//        showTestDialog(0);
        new SetupLEDThread().start();
    }

    void showTestDialog(int i) {
        final int ivalue = i;
        if (i < 3) {
            AlertDialog.Builder b = new AlertDialog.Builder(this);//this为上下文，如果在本类里显示，通常使用this
            b.setTitle("测试结果");//对话框标题
            b.setMessage("i=" + i);//提示文本
            b.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    int nexti = ivalue + 1;
                    showTestDialog(nexti);
                }
            }); //确定按钮，点击事件和取消按钮一样
            AlertDialog alertDialog = b.create();
            alertDialog.show();   //设置完毕，显示对话框
            alertDialog.getWindow().setLayout(800, 400);
        }
    }

    private void ConvertInt2Bytes(int data, byte[] bytes, int iBuffer) {
        bytes[iBuffer] = (byte) ((data & 0xFF000000) >> 24);
        bytes[iBuffer + 1] = (byte) ((data & 0xFF0000) >> 16);
        bytes[iBuffer + 2] = (byte) ((data & 0xFF00) >> 8);
        bytes[iBuffer + 3] = (byte) (data & 0xFF);
    }

    private int GetIntFromBytes(byte[] bytes, int iBuffer) {
        if (bytes == null || bytes.length <= iBuffer + 4)
            return -1;
        return (((bytes[iBuffer] & 0xFF) * 256 + (bytes[iBuffer + 1] & 0xff)) * 256 + (bytes[iBuffer + 2] & 0xff)) * 256 + (bytes[iBuffer + 3] & 0xff);
    }

    int iBufferHead = 0, iBufferData1 = 8, iBufferData2 = 20;
    int nBytesHead = 8, nBytesData1 = 12, nBytesData2 = 32;

    private void ReadCalibrateDataFromDevice12_02() {
        byte[] bytes = new byte[nBytesData2];
        if (!mScanTest.getDevice().ReadMemoBlock(iBufferData2, bytes)) {
            DisplayMessage("从设备读校准数据失败");
            return;
        }
        int iData = 0;
        int type = GetIntFromBytes(bytes, iData * 4); //类型 0胶体金 1荧光
        iData++;
        int brightness = GetIntFromBytes(bytes, iData * 4);
        iData++;
        int start = GetIntFromBytes(bytes, iData * 4);
        iData++;
        int stop = GetIntFromBytes(bytes, iData * 4);
        if (type < 0 || type > 1 || brightness <= 0 || start < 0 || start > 250 || stop < 0 || stop > 250) {
            DisplayMessage("设备中无校准数据或校准数据错误");
            return;
        }
        DisplayMessage("从设备读校准数据成功");
        if (type == 0) {
            ((RadioButton) findViewById(R.id.rbPeakOrValley_Valley)).setChecked(true);
            ((RadioButton) findViewById(R.id.rbPeakOrValley_Peak)).setChecked(false);
        } else {
            ((RadioButton) findViewById(R.id.rbPeakOrValley_Valley)).setChecked(false);
            ((RadioButton) findViewById(R.id.rbPeakOrValley_Peak)).setChecked(true);
        }
        mSBBrightness.setProgress(brightness);
        mEdtStart.setText("" + start);
        mEdtStop.setText("" + stop);
    }

    void SetColor470() {
        if (mbLED470Clicked) {
            color = 0x00;
            if (((CheckBox) findViewById(R.id.cbColor470_1)).isChecked())
                color |= 0x20;
            if (((CheckBox) findViewById(R.id.cbColor470_2)).isChecked())
                color |= 0x08;
            if (((CheckBox) findViewById(R.id.cbColor470_3)).isChecked())
                color |= 0x02;
        }
    }

    //计算峰值下的面积，一共2个峰，峰值左右各1mm，确定是向上的峰或向下的谷
    //左向外10个点及右向外10个点，取平均值，确定为基线
    int left = 10, right = 10, minGap = 20;//面积计算时，极值点左右的距离, minGap为两个峰值间的距离， 单位为0.1mm

    boolean getPeakPos(int[] data, List<Integer> listPeakPos, boolean bValley, int step) {
        int max1 = 0, max2 = 0, max2Left = 0, max2Right = 0;
        int iMax1 = 0, iMax2 = 0;
        if (bValley) {
            for (int iData = 0; iData < data.length; iData++) {
                data[iData] *= -1;
            }
            max2Left = max2Right = max1 = -256 * 256 * 256 * 127;
        }
        //找第1个峰
        for (int iData = 0; iData < data.length; iData++)
            if (data[iData] > max1) {
                max1 = data[iData];
                iMax1 = iData;
            }
        //找第2个峰
        int iMax2Left = 0, iMax2Right = 0;
        if (iMax1 > ((left + right) + left + minGap) * step) {
            for (int iData = left * step; iData < iMax1 - (left + right + minGap) * step; iData++)
                if (data[iData] > max2Left) {
                    max2Left = data[iData];
                    iMax2Left = iData;
                }
        }
        if ((data.length - iMax1) > ((left + right) + right + minGap) * step) {
            for (int iData = iMax1 + (left + right + minGap) * step; iData < data.length - right * step; iData++)
                if (data[iData] > max2Right) {
                    max2Right = data[iData];
                    iMax2Right = iData;
                }
        }
        if (max2Right > max2Left) {
            max2 = max2Right;
            iMax2 = iMax2Right;
        } else {
            max2 = max1;
            max1 = max2Left;
            iMax2 = iMax1;
            iMax1 = iMax2Left;
        }
        listPeakPos.clear();
        if (iMax1 > 0)
            listPeakPos.add(iMax1);
        if (iMax2 > 0)
            listPeakPos.add(iMax2);
        return true;
    }

    private void test() {
        int[] data = {783927, 785035, 784951, 784713, 783965, 784012, 783412, 782620, 782139, 780813, 780487, 781546, 780682, 780528, 780106, 779406, 778550, 777813, 777461, 777337, 777346, 777506, 777237, 777499, 777487, 777980, 779219, 780503, 781459, 782891, 785333, 788439, 792650, 798188, 804672, 811097, 818607, 828033, 837984, 847514, 856924, 866276, 874361, 881749, 887297, 893282, 899681, 903541, 906202, 908513, 908657, 906707, 902774, 897310, 890889, 884061, 875383, 865774, 856879, 848263, 840148, 833206, 826026, 819306, 813383, 807251, 802193, 797185, 792780, 788722, 786331, 784360, 781150, 779447, 779094, 778252, 777132, 775723, 775558, 776291, 775703, 774859, 774359, 774611, 775170, 775426, 775438, 775213, 774715, 774395, 774434, 775340, 775723, 776115, 775575, 775460, 775429, 775891, 775782, 774697, 773926, 775054, 775643, 775660, 775619, 775906, 775827, 775901, 776071, 776523, 776448, 777410, 779166, 780349, 780821, 781913, 783714, 784857, 786113, 786985, 788578, 790215, 790662, 793611, 796170, 797981, 800049, 802828, 805620, 809526, 812790, 817266, 822691, 828884, 835102, 842638, 852357, 862865, 875300, 890393, 907093, 926653, 950133, 975996, 1008788, 1056158, 1131722, 1273338, 1525158, 1900640, 2418689, 3047217, 3729035, 4437266, 5156724, 5827109, 6454021, 6991315, 7433983, 7768117, 8006473, 8153708, 8215496, 8172153, 8050018, 7844756, 7545485, 7141248, 6637422, 6056869, 5446727, 4841287, 4274253, 3759079, 3294081, 2867889, 2489171, 2151433, 1847849, 1600933, 1397736, 1231393, 1102989, 1006186, 934318, 881120, 844617, 822108, 808876, 800760, 795871, 792017, 789470, 786974, 785071, 783778, 781498, 779985, 778805, 777298, 775869, 774737, 773858, 772742, 772079, 770925, 769996, 769489, 768800, 768754, 767622, 767975, 767957, 767074, 766915, 766742, 766202, 766480, 766535, 765901, 765486, 765768, 766098, 766328, 766480, 766106, 765224, 764597, 764348, 764093, 763986, 764442, 764178, 764156, 763728, 763191, 763696, 763958, 763885, 763884, 764596, 765227, 765306, 764850, 764799, 764710, 764629, 765201, 766525, 767165, 767721, 768506, 768829, 769384, 770319, 770683, 772172, 773290, 774400, 775541, 776552, 777791, 775871, 774190, 773943, 773856, 774061, 774318, 774200, 774005, 774192, 774343, 774437, 774039, 773795, 773634, 774117, 774277, 773603, 772818, 773343, 774202, 773832, 773540, 773857, 773468, 773471, 773749, 773611, 773491, 773034, 773223, 773335, 772767, 773247, 773556, 773255, 773094, 772997, 773435, 773527, 772929, 773044, 773401, 772982, 772618, 772624, 772292, 772863, 772879, 772878, 773489, 772995, 772868, 773041, 773549, 772962, 772974, 772878, 772887, 773009, 773329, 772937, 773169, 773138, 772705, 772970, 773313, 773334, 772530, 772353, 772520, 773273, 773013, 772158, 772102, 772282, 772186, 772353, 771775, 772348, 772132, 772548, 772776, 772462, 771545, 771587, 771618, 771849, 772294, 772286, 771986, 772562, 772366, 772239, 771921, 771665, 772095, 773105, 772960, 771700};
        GetArea(data, 2);
    }

    private String GetArea(int[] data, int step) {
        boolean bValley = ((RadioGroup) findViewById(R.id.rgPeakOrValley)).getCheckedRadioButtonId() != R.id.rbPeakOrValley_Peak;
        List<Integer> listPeakPos = new ArrayList<>();
        getPeakPos(data, listPeakPos, bValley, step);
        if (listPeakPos.size() != 2)
            return "";
        Log.d("", "average(直接计算，不去除极值):" + GetAverage(data));
        int average = GetAverage(data, listPeakPos.get(0), listPeakPos.get(1), step);
        int averageInterval = GetAverageInterval(data, listPeakPos.get(0), listPeakPos.get(1), step);

        int[] areaLeft = new int[2];
        int[] areaRight = new int[2];
        int area1 = CalcArea(data, listPeakPos.get(0), step, average, averageInterval, areaLeft);
        int area2 = CalcArea(data, listPeakPos.get(1), step, average, averageInterval, areaRight);
        mArea1 = area1 + "";
        mArea2 = area2 + "";

        int max1 = data[listPeakPos.get(0)], max2 = data[listPeakPos.get(1)];
        SendDispAreaMessage("面积 " + area1 + " " + area2 + " 极值 " + max1 + " " + max2);

        //保存数据
//        saveData();
        return areaLeft[0] + "\t" + areaRight[0] + "\t" + areaLeft[1] + "\t" + areaRight[1] + "\t" + max1 + "\t" + (max1 - average) + "\t" + average;
    }

    //给定点，算左右1mm的面积
    //首先计算左点外10个点和右点外10个点的平均值
    //再计算左右1mm内值减去平均值后的面积
    int nPointsForAverageLeft = 10, nPointsForAverageRight = 10;

    private int CalcArea(int[] data, int iMax, int step, int averageGlobal, int averageInterval, int[] area2) {
        int nData = 0, sum = 0;
        for (int iData = iMax - left * step - nPointsForAverageLeft * step; iData < iMax - left * step; iData++) {
            if (iData <= 0)
                continue;
            sum += data[iData];
            nData++;
        }
        for (int iData = iMax + right * step; iData < iMax + right * step + nPointsForAverageRight * step; iData++) {
            if (iData >= data.length)
                break;
            sum += data[iData];
            nData++;
        }
        if (nData == 0)
            return -1;
        int average = sum / nData;
        int area = 0, areaSubGlobalAvg = 0, areaSubIntervalAvg = 0;
        for (int iData = iMax - left * step; iData < iMax + right * step; iData++) {
            if (iData < 0 || iData >= data.length) {
                Log.d("area", "Data index error:" + iData);
                continue;
            }
            area += (data[iData] - average) / step;
            areaSubGlobalAvg += (data[iData] - averageGlobal) / step;
            areaSubIntervalAvg += (data[iData] - averageInterval) / step;
        }
        Log.d("", "area: " + area + " average: " + average);
        Log.d("", "areaSubGlobalAvg: " + areaSubGlobalAvg + " averageGlobal: " + averageGlobal);
        Log.d("", "areaSubIntervalAvg: " + areaSubIntervalAvg + " averageInterval: " + averageInterval);
        if (area2 != null) {
            area2[0] = area;
            area2[1] = areaSubGlobalAvg;
        }
        return area;
    }

    private void ResetBtnClicked() {
        mBtn670.setBackgroundColor(Color.BLUE);
        mBtn365.setBackgroundColor(Color.BLUE);
        mBtn470.setBackgroundColor(Color.BLUE);
        mBtn525_1.setBackgroundColor(Color.BLUE);
        mBtn525_2.setBackgroundColor(Color.BLUE);
        mBtn525All.setBackgroundColor(Color.BLUE);

        mBtn364.setBackgroundColor(Color.BLUE);
        mBtn470_2.setBackgroundColor(Color.BLUE);
        mBtn525_3.setBackgroundColor(Color.BLUE);
        mBtnLEDOn_2.setBackgroundColor(Color.BLUE);

        mBtnLEDClicked = null;
    }

    private void SetBtnClicked(Button btn) {
        ResetBtnClicked();
        btn.setBackgroundColor(Color.CYAN);
        mBtnLEDClicked = btn;
    }

    private void OpenLED_2() {
        SetBtnClicked(mBtnLEDOn_2);
        String colorText = ((EditText) findViewById(R.id.edtColor)).getText().toString();
        if (colorText.length() != 2) {
            Toast.makeText(this, "颜色值位数不是2位", Toast.LENGTH_LONG).show();
            return;
        }
        color = Utils.hexString2byte(colorText);
        LEDOn();
    }

    private void OpenLED364() {
        SetBtnClicked(mBtn364);
        color = (byte) 0x20;
        LEDOn();
    }

    private void OpenLED470_2() {
        SetBtnClicked(mBtn470_2);
        color = (byte) 0x11;
        LEDOn();
    }

    private void OpenLED525_3() {
        SetBtnClicked(mBtn525_3);
        color = 0x02;
        LEDOn();
    }

    private void OpenLED670() {
        SetBtnClicked(mBtn670);
        color = 0x02;
        LEDOn();
    }

    private void OpenLED365() {
        SetBtnClicked(mBtn365);
        color = 0x15;
        LEDOn();
    }

    private void OpenLED470() {
        SetBtnClicked(mBtn470);
        mbLED470Clicked = true;
        SetColor470();
        LEDOn();
    }

    private void OpenLED525_1() {
        SetBtnClicked(mBtn525_1);
        color = 0x40;
        LEDOn();
    }

    private void OpenLED525_2() {
        SetBtnClicked(mBtn525_2);
        color = (byte) 0x80;
        LEDOn();
    }

    private void OpenLED525All() {
        SetBtnClicked(mBtn525All);
        color = (byte) 0x3f;
        LEDOn();
    }

    //用户点击了灯，设置下灯的位
    private void SetColor() {
        color = 0x00;
        if (mcbColor1.isChecked())
            color |= 0x01;
        if (mcbColor2.isChecked())
            color |= 0x02;
        if (mcbColor3.isChecked())
            color |= 0x04;
        if (mcbColor4.isChecked())
            color |= 0x08;
        if (mcbColor5.isChecked())
            color |= 0x10;
        if (mcbColor6.isChecked())
            color |= 0x20;
    }

    private void LEDOn() {
//        ledPosition = 0x03;
        int brightness = mSBBrightness.getProgress();
        if (!mScanTest.getDevice().LEDOn(ledPosition, color, brightness))
            DisplayMessage("开灯失败");
        else
            DisplayMessage("开灯成功");
    }

    private void LEDOff() {
        ResetBtnClicked();
//        if (!mScanTest.getDevice().LEDOff())
//        ledPosition = 0x03;
        if (!mScanTest.getDevice().LEDOn(ledPosition, (byte) 0x00, 0))
            DisplayMessage("关灯失败");
        else
            DisplayMessage("关灯成功");
    }

    private void Home() {
        if (!mScanTest.getDevice().GoHome())
            DisplayMessage("回原点失败");
        else
            DisplayMessage("回原点成功");
    }

    private void TrayOut() {
        if (!mScanTest.getDevice().TrayOut())
            DisplayMessage("托架取出失败");
        else
            DisplayMessage("托架取出成功");
    }

    private void TrayIn() {
        if (!mScanTest.getDevice().TrayIn())
            DisplayMessage("托架移动进入失败");
        else
            DisplayMessage("托架移动进入成功");
    }

    private void TrayMoveStart() {
        int dist = Integer.parseInt(mEdtStart.getText().toString());
        if (!mScanTest.getDevice().MoveTray(dist, high_speed))
            DisplayMessage("托架移动起点失败");
        else
            DisplayMessage("托架移动起点成功");
    }

    private void TrayMoveEnd() {
        int dist = Integer.parseInt(mEdtStop.getText().toString());
        if (dist > 250) {
            dist = 250;
            mEdtStop.setText("250");
        }
        if (!mScanTest.getDevice().MoveTray(dist, high_speed))
            DisplayMessage("托架移动终点失败");
        else
            DisplayMessage("托架移动终点成功");
    }

    //    private void Read() {
//        int[] data = new int[10];
//        String strADGain = mEdtADGain.getText().toString();
//        if (!mScanTest.getDevice().GetAD(adPosition, (byte) Integer.parseInt(strADGain), data)) {
//            DisplayMessage("读数据失败");
//            return;
//        }
//        DisplayData(data);
//    }
//    private void DisplayData(int[] data) {
//        String csMsg = "";
//        for (int i = 0; i < 10; i++) {
//            csMsg += mstrWaveLength[i] + ":" + data[i] + "\t";
//        }
//        DisplayMessage(csMsg);
//    }
    private void Read() {
        getADPosition();
        String strADGain = mEdtADGain.getText().toString();
        mScanTest.getDevice().StartADReceive(adPosition);
        mScanTest.getDevice().GetADAfterStart();
        mScanTest.getDevice().GetADAfterStart();
        mScanTest.getDevice().GetADAfterStart();
        int data = mScanTest.getDevice().GetADAfterStart();
        mScanTest.getDevice().StopADReceive();
        if (data < 0) {
            DisplayMessage("读数据失败");
            return;
        }
        DisplayMessage("AD:" + data);
    }

    private void getADPosition() {
        getADPosition(mrgADPosition.getCheckedRadioButtonId());
    }

    private void getADPosition(int adPositionId) {
        if (!mcbLaserScan.isChecked()) { //是否激光扫描
            if (adPositionId == R.id.rbADPosition1) {
                adPosition = 0x01;
                ledPosition = 0x03;
            } else {
                adPosition = 0x02;
                ledPosition = 0x04;
            }
        } else {
            if (adPositionId == R.id.rbADPosition1) {
                adPosition = 0x01;
            } else {
                adPosition = 0x02;
            }
        }
    }

    void getStartStop() {
        mStart = Integer.parseInt(mEdtStart.getText().toString());
        mStop = Integer.parseInt(mEdtStop.getText().toString());
        if (mStop > 250) {
            mStop = 250;
            mEdtStop.setText("250");
        }
        if (!getStep())
            mStep = Integer.parseInt(mEdtStep.getText().toString());
    }

    private void ScanRead() {
        getStartStop();
        getADPosition();

        saveSettings();
        mScanTest.setValley(!SettingsClass.getMainPeak());

        mListResult.clear();
        mScanTest.DoTest(mStart, mStop);
    }

    private void ScanReadAMS() {
        getStartStop();
        getADPosition();

        saveSettings();

        new TestAMS().start();
    }

    private void scanReadAfterCalibrateBrightness() {
        getStartStop();
        getADPosition();
        readCalibrationFromDevice();

        int brightness = (gain + 1) * (amplify & 0xff);
        mSBBrightness.setProgress(brightness);
//        new Test(mStart, mStop, gain, amplify, color).start();
        mScanTest.DoTest(mStart,mStop,brightness,color);
    }

    private void ScanReadNoMove() {
        getStartStop();
        getADPosition();

        saveSettings();

        new Test(false).start();
    }

    private void saveSettings() {
        SettingsClass.setMainBrightness(mSBBrightness.getProgress());
        SettingsClass.setMainStart(mStart);
        SettingsClass.setMainStop(mStop);
        if (((RadioGroup) findViewById(R.id.rgPeakOrValley)).getCheckedRadioButtonId() == R.id.rbPeakOrValley_Peak)
            SettingsClass.setMainPeak(true);
        else SettingsClass.setMainPeak(false);
        if (((RadioGroup) findViewById(R.id.rgADPosition)).getCheckedRadioButtonId() == R.id.rbADPosition1)
            SettingsClass.setMainADPosition(1);
        else SettingsClass.setMainADPosition(2);

        SettingsClass.saveSettings();
    }

    int iStrip = 0;
    String resultFileName;
    int[] frequencyAndGain = new int[2];

    boolean getStep() {
        if (!mScanTest.getDevice().GetADCFrequencyAndGain((byte) 0x01, frequencyAndGain))
            return false;
        if (frequencyAndGain[0] < 10 || frequencyAndGain[0] > 19200)
            return false;
        mStep = (int) (frequencyAndGain[0] / 12.5 + 0.5);
        if (mStep <= 0)
            mStep = 1;
        return true;
    }

    private void ScanRead10() {
        getStartStop();
        getADPosition();

        saveSettings();

        if (!readCalibrationFromDevice()) {
            amplify = 48;
            SendDispMessage("读设备校准值失败 gain: " + gain + " amplify: " + amplify);
//            return;
        }
        iStrip = 0;
        resultFileName = getDataFilename();
        appendTest10Data(resultFileName, "测试时间：" + getDateString() + " 亮度gain: " + gain + " amplify: " + amplify + "\r\n");
        appendTest10Data(resultFileName, "测试条No.\t面积1-左侧平均\t面积2-左侧平均\t面积1-总平均\t面积2-总平均\t极值1\t极值1相对值\t平均值\r\n");
        appendTest10Data(resultFileName, "测试条：" + (iStrip + 1) + "\t");
        showStripDialog();
    }

    //把测试数据保存下来
    private boolean appendTest10Data(String filename, String data) {
        try {
            FileOutputStream out = new FileOutputStream(resultFileName, true);
            out.write(data.getBytes());
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    void nextStrip() {
        iStrip++;
        if (iStrip < 8) {
            appendTest10Data(resultFileName, "测试条：" + (iStrip + 1) + "\t");
            showStripDialog();
        }
    }

    void showStripDialog() {
        AlertDialog.Builder b = new AlertDialog.Builder(this);//this为上下文，如果在本类里显示，通常使用this
        b.setTitle("提示");//对话框标题
        b.setMessage("插入测试条：" + (iStrip + 1));//提示文本
        b.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                new Test10().start();
            }
        }); //确定按钮，点击事件和取消按钮一样
        AlertDialog alertDialog = b.create();
        alertDialog.show();   //设置完毕，显示对话框
        alertDialog.getWindow().setLayout(800, 400);
    }

    void SendDispMessage(String str) {
        Message message = new Message();
        message.what = 1;
        message.obj = str;
        mHandler.sendMessage(message);
    }

    void SendDispAreaMessage(String str) {
        Message message = new Message();
        message.what = 5;
        message.obj = str;
        mHandler.sendMessage(message);
    }

    void SendDispAverageMessage(String str) {
        Message message = new Message();
        message.what = 6;
        message.obj = str;
        mHandler.sendMessage(message);
    }

    void SendDispData(int[] data) {
        Message message = new Message();
        message.what = 2;
        message.obj = data;
        mHandler.sendMessage(message);
    }

    void SendDispData(int data) {
        Message message = new Message();
        message.what = 4;
        message.obj = data;
        mHandler.sendMessage(message);
    }

    void DispCurve() {
        Message message = new Message();
        message.what = 3;
        mHandler.sendMessage(message);
    }

    public File getSaveFile() {
        File file = null;
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            file = Environment.getExternalStorageDirectory();
        } else {
            file = getFilesDir();
        }

        if (file != null) {
            file = new File(file, "stresscube");
            if (!file.exists()) {
                file.mkdir();
            }
            file = new File(file, "scantestpd");
            if (!file.exists()) {
                file.mkdir();
            }
        }

        return file;
    }

    public String getDateString() {
        Calendar c = Calendar.getInstance();
        c.setTime(new Date(System.currentTimeMillis()));
        String formatString = "yyyyMMddHHmmss";
        SimpleDateFormat sdf = new SimpleDateFormat(formatString, Locale.ENGLISH);
        return sdf.format(c.getTime());
    }

    private String getDataFilename() {
        return getSaveFile() + "/" + getDateString() + ".txt";
    }

    @Override
    public void GotData(int data) {
        mListResult.add(data);
        DispCurve();
    }

    @Override
    public void GotData(int[] data) {

    }
    private int getPosition(int pos) {
        return mScanTest.start+pos/mScanTest.step;
    }
    private int getLeft(){
        return getPosition(mScanTest.peakLeft);
    }
    private int getRight(){
        return getPosition(mScanTest.peakRight);
    }
    @Override
    public void Notify(int status) {
        if(status==TestCallback.STATUS_TEST_SUCCESS) {
            String strMsg="测试完成: "+mScanTest.mArea1+"@"+getLeft()+" "+mScanTest.mArea2+"@"+getRight();
            SendDispMessage(strMsg);
        }else if(status==TestCallback.STATUS_TEST_FAIL)
            SendDispMessage("测试出错");
        else if(status==TestCallback.STATUS_TEST_START)
            SendDispMessage("开始测试");
        else if(status==TestCallback.STATUS_OPEN_LED_FAIL)
            SendDispMessage("开灯失败");
        else if(status==TestCallback.STATUS_MOVE_TRAY_TO_START_FAIL)
            SendDispMessage("移动到起点失败");
        else if(status==TestCallback.STATUS_TEST_FORCE_STOP)
            SendDispMessage("没有接收到停止信号，自动停止");
    }

    class Test extends Thread {
        boolean bMove = true;
        boolean bCalibrateBrightness = false;
        int start, end;
        byte gain, amplify, color;

        public Test(boolean bMove) {
            this.bMove = bMove;
        }

        public Test(int start, int end, byte gain, byte amplify, byte color) {
            bCalibrateBrightness = true;
            this.start = start;
            this.end = end;
            this.gain = gain;
            this.amplify = amplify;
            this.color = color;
        }

        public Test() {
        }

        @Override
        public void run() { //改成发移动命令、连续获取AD、检测停止命令
            SendDispMessage("开始测试");

            if (bCalibrateBrightness) {
                if (!scanReadAD(true, color, gain, amplify, start, end, mStep, mListResult, bMove))
                    return;
            } else {
                if (!scanReadAD(false, (byte) 0, (byte) 0, (byte) 0, mStart, mStop, mStep, mListResult, bMove))
                    return;
            }

            if (mListResult.size() > 10) {
                int[] data = new int[mListResult.size()];
                for (int i = 0; i < mListResult.size(); i++)
                    data[i] = mListResult.get(i);
                GetArea(data, mStep);
                if (SaveData(data))
                    DisplayMessage("保存数据成功");
                else
                    DisplayMessage("保存失败！");
                if (SendData(data))
                    DisplayMessage("上传数据成功");
                else
                    DisplayMessage("上传失败！");
            }
        }

        private byte[] int2Bytes(int data) {
            byte[] bytes = new byte[4];
            bytes[0] = (byte) ((data >> 24) & 0xFF);
            bytes[1] = (byte) ((data >> 16) & 0xFF);
            bytes[2] = (byte) ((data >> 8) & 0xFF);
            bytes[3] = (byte) (data & 0xFF);
            return bytes;
        }

        private String intArray2Base64String(int[] data) {
            byte[] byteData = new byte[data.length * 4];
            for (int i = 0; i < data.length; i++) {
                byte[] bytes = int2Bytes(data[i]);
                byteData[i * 4] = bytes[0];
                byteData[i * 4 + 1] = bytes[1];
                byteData[i * 4 + 2] = bytes[2];
                byteData[i * 4 + 3] = bytes[3];
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                return Base64.getEncoder().encodeToString(byteData);
            }
            return "NoData";
        }

        private boolean SendData(int[] data) {
            JSONObject obj = new JSONObject();
            String ledWaveLength = "";
            if (mBtnLEDClicked != null) {
                if (mBtnLEDClicked == mBtn364)
                    ledWaveLength = "370";
                else if (mBtnLEDClicked == mBtn470_2)
                    ledWaveLength = "470";
                else if (mBtnLEDClicked == mBtn670)
                    ledWaveLength = "525";
                else if (mBtnLEDClicked == mBtn365)
                    ledWaveLength = "365";
            } else {
                ledWaveLength = String.valueOf(Utils.hexString2byte(((EditText) findViewById(R.id.edtColor)).getText().toString()));
            }
            try {
                obj.put("CreateTime", SCTimeUtils.getFormatData03(System.currentTimeMillis()));
                obj.put("AppName", "ScanPDTest");
                obj.put("Data", intArray2Base64String(data));
                obj.put("Bits", 32);
                obj.put("Frequency", frequencyAndGain[0]);
                obj.put("Size", data.length);
                obj.put("StartPos", mStart);
                obj.put("EndPos", mStop);
                obj.put("Brightness", mSBBrightness.getProgress());
                obj.put("LEDPosition", ledPosition);
                obj.put("ADPosition", adPosition);
                obj.put("PeakValley", (((RadioGroup) findViewById(R.id.rgPeakOrValley)).getCheckedRadioButtonId() != R.id.rbPeakOrValley_Peak) ? 1 : 2);
                obj.put("WaveLength", ledWaveLength);
                obj.put("Comment", GetDeviceName() + DeviceUtils.getDeviceInfo(context));
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            WebApi webApi = new WebApi();
            WebApi.HttpListener cb = new WebApi.HttpListener() {
                public boolean onResponse(String response) {
                    SendDispMessage("Post成功\r\n" + response);
                    return true;
                }

                public void onSuccess(JSONObject response) {
                    SendDispMessage("Post成功\r\n" + response.toString());
                }

                public void onFailed(String message, int status) {
                    SendDispMessage("Post失败 code:" + status + "\r\n" + message);
                }
            };
            webApi.post(mstrServerIP + "ScanPD/", obj.toString(), cb);
            return true;
        }

        //把测试数据保存下来
        private boolean SaveData(int[] data) {
            byte position = 0x01, indexLED = 0x02;
            try {
                String resultFileName = getDataFilename();
                FileOutputStream out = new FileOutputStream(resultFileName);
                out.write(("" + mStart + " -> " + mStop + "\r\n").getBytes());
                out.write(("面积1: " + mArea1 + " 面积2:" + mArea2 + "\r\n").getBytes());
                for (int i = 0; i < data.length; i++) {
                    out.write(("" + data[i] + "\r\n").getBytes());
                }
                out.flush();
                out.close();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }

    class TestAMS extends Thread {
        boolean bMove = true;
        boolean bCalibrateBrightness = false;
        int start, end;
        byte gain, amplify, color;

        public TestAMS() {
        }

        @Override
        public void run() { //改成发移动命令、连续获取AD、检测停止命令
            SendDispMessage("开始测试");

            int rbID=((RadioGroup)findViewById(R.id.rgAMSGain)).getCheckedRadioButtonId();
            adAMSGain=(byte)Integer.parseInt(((RadioButton)findViewById(rbID)).getText().toString());
            if (!scanReadAMS(false, (byte) 0, (byte)0, (byte) 0, mStart, mStop, mStep, mListResult, bMove))
                return;

            if (mListResult.size() > 10) {
                int[] data = new int[mListResult.size()];
                for (int i = 0; i < mListResult.size(); i++)
                    data[i] = mListResult.get(i);
                GetArea(data, mStep);
                if (SaveData(data))
                    DisplayMessage("保存数据成功");
                else
                    DisplayMessage("保存失败！");
                if (SendData(data))
                    DisplayMessage("上传数据成功");
                else
                    DisplayMessage("上传失败！");
            }
        }

        private byte[] int2Bytes(int data) {
            byte[] bytes = new byte[4];
            bytes[0] = (byte) ((data >> 24) & 0xFF);
            bytes[1] = (byte) ((data >> 16) & 0xFF);
            bytes[2] = (byte) ((data >> 8) & 0xFF);
            bytes[3] = (byte) (data & 0xFF);
            return bytes;
        }

        private String intArray2Base64String(int[] data) {
            byte[] byteData = new byte[data.length * 4];
            for (int i = 0; i < data.length; i++) {
                byte[] bytes = int2Bytes(data[i]);
                byteData[i * 4] = bytes[0];
                byteData[i * 4 + 1] = bytes[1];
                byteData[i * 4 + 2] = bytes[2];
                byteData[i * 4 + 3] = bytes[3];
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                return Base64.getEncoder().encodeToString(byteData);
            }
            return "NoData";
        }

        private boolean SendData(int[] data) {
            JSONObject obj = new JSONObject();
            String ledWaveLength = "";
            if (mBtnLEDClicked != null) {
                if (mBtnLEDClicked == mBtn364)
                    ledWaveLength = "370";
                else if (mBtnLEDClicked == mBtn470_2)
                    ledWaveLength = "470";
                else if (mBtnLEDClicked == mBtn670)
                    ledWaveLength = "525";
                else if (mBtnLEDClicked == mBtn365)
                    ledWaveLength = "365";
            } else {
                ledWaveLength = String.valueOf(Utils.hexString2byte(((EditText) findViewById(R.id.edtColor)).getText().toString()));
            }
            try {
                obj.put("CreateTime", SCTimeUtils.getFormatData03(System.currentTimeMillis()));
                obj.put("AppName", "ScanPDTest");
                obj.put("Data", intArray2Base64String(data));
                obj.put("Bits", 32);
                obj.put("Frequency", frequencyAndGain[0]);
                obj.put("Size", data.length);
                obj.put("StartPos", mStart);
                obj.put("EndPos", mStop);
                obj.put("Brightness", mSBBrightness.getProgress());
                obj.put("LEDPosition", ledPosition);
                obj.put("ADPosition", adPosition);
                obj.put("PeakValley", (((RadioGroup) findViewById(R.id.rgPeakOrValley)).getCheckedRadioButtonId() != R.id.rbPeakOrValley_Peak) ? 1 : 2);
                obj.put("WaveLength", ledWaveLength);
                obj.put("Comment", GetDeviceName() + DeviceUtils.getDeviceInfo(context));
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            WebApi webApi = new WebApi();
            WebApi.HttpListener cb = new WebApi.HttpListener() {
                public boolean onResponse(String response) {
                    SendDispMessage("Post成功\r\n" + response);
                    return true;
                }

                public void onSuccess(JSONObject response) {
                    SendDispMessage("Post成功\r\n" + response.toString());
                }

                public void onFailed(String message, int status) {
                    SendDispMessage("Post失败 code:" + status + "\r\n" + message);
                }
            };
            webApi.post(mstrServerIP + "ScanPD/", obj.toString(), cb);
            return true;
        }

        //把测试数据保存下来
        private boolean SaveData(int[] data) {
            byte position = 0x01, indexLED = 0x02;
            try {
                String resultFileName = getDataFilename();
                FileOutputStream out = new FileOutputStream(resultFileName);
                out.write(("" + mStart + " -> " + mStop + "\r\n").getBytes());
                out.write(("面积1: " + mArea1 + " 面积2:" + mArea2 + "\r\n").getBytes());
                for (int i = 0; i < data.length; i++) {
                    out.write(("" + data[i] + "\r\n").getBytes());
                }
                out.flush();
                out.close();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }

    private String GetDeviceName() {
        ParaName para = mScanTest.getDevice().readParaNameFromDevice();
        if (para == null)
            return "";
        return (para.name + " " + para.serialNo + " ");
    }

    //测试10次，看稳定性
    class Test10 extends Thread {
        String resultString = "";

        @Override
        public void run() { //改成发移动命令、连续获取AD、检测停止命令
            SendDispMessage("开始" + (iStrip + 1) + "号条10次测试");
            for (int i = 0; i < 1; i++) {
                if (i != 0) {
                    try {
                        Thread.sleep(30 * 1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    }
                }
                SendDispMessage("开始第" + (i + 1) + "次测试");
                if (!test()) {
                    SendDispMessage("10次测试失败");
                    break;
                }
            }
            SendDispMessage("10次测试结束");
//            saveTest10Data();
            SendDispMessage("10次测试保存结果结束");
            mHandler.sendEmptyMessage(7);
        }

        boolean test() {
            if (!scanReadAD(true, testColor, gain, amplify, mStart, mStop, mStep, mListResult))
                return false;

            super.run();

            if (mListResult.size() > 10) {
                int[] data = new int[mListResult.size()];
                for (int i = 0; i < mListResult.size(); i++)
                    data[i] = mListResult.get(i);
                appendTest10Data(resultFileName, GetArea(data, mStep) + "\r\n");
            } else
                return false;
            return true;
        }

        //把测试数据保存下来
        private boolean saveTest10Data() {
            try {
                String resultFileName = getDataFilename();
                FileOutputStream out = new FileOutputStream(resultFileName);
                out.write(resultString.getBytes());
                out.flush();
                out.close();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        //把测试数据保存下来
        private boolean appendTest10Data(String filename, String data) {
            try {
                FileOutputStream out = new FileOutputStream(filename, true);
                out.write(data.getBytes());
                out.flush();
                out.close();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }

    private int GetAverage(int[] data) {
        double sum = 0;
        for (int i = 0; i < data.length; i++)
            sum += data[i];
        return (int) (sum / data.length + 0.5);
    }

    private int GetAverage(int[] data, int iMaxLeft, int iMaxRight, int step) {
        int[] newData = new int[data.length];
        for (int i = 0; i < data.length; i++)
            newData[i] = data[i];
        for (int i = 0; i < left; i++)
            newData[i] = -1;
        for (int i = iMaxLeft - left * step; i <= iMaxLeft + right * step; i++) {
            if (i <= 0)
                continue;
            if (i >= data.length)
                break;
            newData[i] = -1;
        }
        for (int i = iMaxRight - left * step; i <= iMaxRight + right * step; i++) {
            if (i <= 0)
                continue;
            if (i >= data.length)
                break;
            newData[i] = -1;
        }
        int average = calAverage(newData);

        SendDispAverageMessage("平均值 ：" + average);
        return average;
    }

    double threshold_in_average = 1.02;
    int minimun_numbers_in_average = 10;

    int calAverage(int[] data) {
        while (true) {
            double sum = 0;
            int num = 0;
            int max = -1, imax = -1;
            int min = 0, imin = -1;
            for (int i = 0; i < data.length; i++)
                if (data[i] > 0) {
                    sum += data[i];
                    num++;
                    if (imax < 0 || max < data[i]) {
                        max = data[i];
                        imax = i;
                    }
                    if (imin < 0 || min > data[i]) {
                        min = data[i];
                        imin = i;
                    }
                }
            int average = (int) (sum / num + 0.5);
            if (num <= minimun_numbers_in_average)
                return average;
            if (max < average * threshold_in_average && min > average / threshold_in_average)
                return average;
            if (max * 1.0 / average > average * 1.0 / min)
                data[imax] = -1;
            else
                data[imin] = -1;
        }
    }

    private int GetAverageInterval(int[] data, int iMaxLeft, int iMaxRight, int step) {
        int iStart = iMaxLeft + right * step;
        int iEnd = iMaxRight - left * step;
        int len = iEnd - iStart + 1;
        int[] newData = new int[len];
        for (int i = 0; i < len; i++)
            newData[i] = data[iStart + i];
        int average = calAverage(newData);
        SendDispAverageMessage("中间平均值 ：" + average);
        return average;
    }

    Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    DisplayMessage((String) msg.obj);
                    break;
                case 2:
//                    DisplayData((int[]) msg.obj);
                    break;
                case 3:
                    DrawLineChart();
                    break;
                case 4:
                    DisplayMessage("AD: " + (int) msg.obj);
                    break;
                case 5:
                    DisplayAreaMessage((String) msg.obj);
                    break;
                case 6:
                    DisplayAverageMessage((String) msg.obj);
                    break;
                case 7:
                    nextStrip();
                    break;
            }
            super.handleMessage(msg);
        }
    };

    private void ClickF8ClearNIR(int i) {
        bF8ClearNIR[i - 1] = !bF8ClearNIR[i - 1];
        DrawLineChart();
    }

    int times=0, nTimes=5;
    private void DrawLineChart() {
        if (mListResult == null || mListResult.size() <= 0) {
            Toast.makeText(this, "没有数据", Toast.LENGTH_LONG).show();
            return;
        }

        times++;
        if(times%nTimes!=0)
            return;

        List<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
//        for (int fx = 0; fx < 10; fx++) {
//            if (!bF8ClearNIR[fx]) continue;
        List<Entry> entries = new ArrayList<Entry>();
//            for (int i = 0; i < mListResult.get(fx).size(); i++) {
//                entries.add(new Entry(mStart + i * mStep, mListResult.get(fx).get(i)));
//            }
        for (int i = 0; i < mListResult.size(); i++)
            entries.add(new Entry(mStart + i * 1.0f / mStep, mListResult.get(i)));
//            LineDataSet dataSet = new LineDataSet(entries, mstrWaveLength[fx]);
//        int color = GetColor(fx);
        LineDataSet dataSet = new LineDataSet(entries, "ad");
        int color = GetColor(0);
        dataSet.setColor(color);
        dataSet.setValueTextColor(color);
        dataSet.setCircleColor(color);
        dataSet.setCircleHoleColor(color);
        dataSet.setDrawCircles(false);
        dataSet.setDrawValues(false);
        dataSets.add(dataSet);
//        }
        LineData data = new LineData(dataSets);
        mLineChart.setData(data);
        mLineChart.invalidate(); // refresh
    }

    int[] colors = {Color.RED, Color.GREEN, Color.BLUE, Color.GRAY, Color.DKGRAY, Color.LTGRAY, Color.CYAN, Color.BLACK, Color.MAGENTA, Color.WHITE};

    private int GetColor(int i) {
        return colors[i % 10];
    }

    /**
     * 保存数据
     */
    private void saveData() {
        DataBean dataBean = new DataBean();
        dataBean.time = System.currentTimeMillis();
        //编号
        dataBean.number = etNumber.getText().toString().trim();
        dataBean.create_time = SCTimeUtils.getFormatData03(dataBean.time);

        dataBean.project = etProject.getText().toString().trim();

        //两个面积
        dataBean.area1 = mArea1;
        dataBean.area2 = mArea2;

        dataBean.ad = ((EditText) findViewById(R.id.edtADGain)).getText().toString().trim();
        dataBean.start = ((EditText) findViewById(R.id.edtStart)).getText().toString().trim();
        dataBean.stop = ((EditText) findViewById(R.id.edtStop)).getText().toString().trim();
        //步长
        dataBean.step = ((EditText) findViewById(R.id.edtStep)).getText().toString().trim();
        //波长
        dataBean.waveLength = waveLength;
        //亮度
        dataBean.brightness = ((TextView) findViewById(R.id.tvBrightness)).getText().toString().trim();

        if (((RadioButton) findViewById(R.id.rbPeakOrValley_Peak)).isChecked()) {
            //选择的是胶体金
            dataBean.jtj_or_yg = "1";
        } else {
            dataBean.jtj_or_yg = "2";
        }

        dataBean.save();
    }

    boolean scanReadAD(boolean bOpenLed, byte color, byte gain, byte amplify, int start, int stop, int step, List<Integer> listResult) {
        return scanReadAD(bOpenLed, color, gain, amplify, start, stop, step, listResult, true);
    }

    boolean scanReadAD(boolean bOpenLed, byte color, byte gain, byte amplify, int start, int stop, int step, List<Integer> listResult, boolean bMove) {
        mScanTest.getDevice().StopADReceive();
        mScanTest.getDevice().Skip();
        if (bMove && !mcbLaserScan.isChecked())
            mScanTest.getDevice().GoHome();

        if (bOpenLed && !mScanTest.getDevice().LEDOn(ledPosition, color, gain, amplify)) {
            SendDispMessage("开灯失败");
            return false;
        }
        listResult.clear();
        mScanTest.getDevice().Skip();

        if (bMove)
            if (!mScanTest.getDevice().MoveTray(start, high_speed)) {
                if (!mScanTest.getDevice().MoveTray(start, high_speed)) {
                    SendDispMessage("移动到起点位置 " + start + " 失败");
                    mScanTest.getDevice().StopADReceive();
                    if (bOpenLed)
                        mScanTest.getDevice().LEDOn(ledPosition, (byte) 0x00, 0);
                    mScanTest.getDevice().MoveTray(0, high_speed);
                    return false;
                }
            }
//        if(bMove) {
//            int iTime=0;
//            while (!mScanTest.getDevice().MoveTray(start, (byte)1)) {
//                try {
//                    Thread.sleep(1000);
//                } catch (Exception e) {
//                }
//                iTime++;
//                if(iTime>=10)
//                    break;
//            }
//        }

        mScanTest.getDevice().StartADReceive(adPosition);
        if (bMove) mScanTest.getDevice().StartMoveTray(stop, normal_speed);
        mScanTest.getDevice().GetADAfterStart();
        mScanTest.getDevice().GetADAfterStart();
        mScanTest.getDevice().GetADAfterStart();
        int nData = 0;
        while (true) { //连续读
            int data = mScanTest.getDevice().GetADAfterStart();
            if (data <= 0 && bMove) {
                break;
            }
            listResult.add(data);
            DispCurve();
            nData++;
            if (nData > (stop - start) * step + 100) {
                SendDispMessage("没有接收到停止命令，强制停止");
                break;
            }
        }
        mScanTest.getDevice().StopADReceive();
        if (bOpenLed)
            mScanTest.getDevice().LEDOn(ledPosition, (byte) 0x00, 0);
        if (bMove) mScanTest.getDevice().MoveTray(0, high_speed);
        return true;
    }
    boolean scanReadAMS(boolean bOpenLed, byte color, byte gain, byte amplify, int start, int stop, int step, List<Integer> listResult, boolean bMove) {
        mScanTest.getDevice().StopADReceive();
        mScanTest.getDevice().Skip();
        if (bMove && !mcbLaserScan.isChecked())
            mScanTest.getDevice().GoHome();

        if (bOpenLed && !mScanTest.getDevice().LEDOn(ledPosition, color, gain, amplify)) {
            SendDispMessage("开灯失败");
            return false;
        }
        listResult.clear();
        mScanTest.getDevice().Skip();

        if (bMove)
            if (!mScanTest.getDevice().MoveTray(start, high_speed)) {
                if (!mScanTest.getDevice().MoveTray(start, high_speed)) {
                    SendDispMessage("移动到起点位置 " + start + " 失败");
                    mScanTest.getDevice().StopADReceive();
                    if (bOpenLed)
                        mScanTest.getDevice().LEDOn(ledPosition, (byte) 0x00, 0);
                    mScanTest.getDevice().MoveTray(0, high_speed);
                    return false;
                }
            }

        if (bMove) mScanTest.getDevice().StartMoveTray(stop, normal_speed);
        mScanTest.getDevice().GetADAfterStart();

        int nData = 0;
        while (true) { //连续读
            int[] data=new int[10];
            if(!mScanTest.getDevice().GetAD_AMS(adAMSPosition, adAMSGain, data))
                break;
            if (data[8] <= 0 && bMove) {
                break;
            }
            listResult.add(data[8]);
            DispCurve();
            nData++;
            if (nData > (stop - start) * step + 100) {
                SendDispMessage("没有接收到停止命令，强制停止");
                break;
            }
        }
        if (bOpenLed)
            mScanTest.getDevice().LEDOn(ledPosition, (byte) 0x00, 0);
        if (bMove) mScanTest.getDevice().MoveTray(0, high_speed);
        return true;
    }

    int getMaxPeak(byte gain, byte amplify) {
        if (!scanReadAD(true, testColor, gain, amplify, mStart, mStop, mStep, mListResult))
            return -1;

        int max = 0;
        for (int i = 0; i < mListResult.size(); i++) {
            if (mListResult.get(i) > max)
                max = mListResult.get(i);
        }
//        SendDispMessage("gain " + gain + " amplify " + amplify + " 最大值 " + max);
        return max;
    }

    int getMaxPeakSubMean(byte gain, byte amplify) {
        int max = getMaxPeak(gain, amplify);
        if (max <= 0)
            return -1;
        if (mListResult.size() < 10)
            return -1;
        int[] data = new int[mListResult.size()];
        for (int i = 0; i < mListResult.size(); i++)
            data[i] = mListResult.get(i);

        boolean bValley = ((RadioGroup) findViewById(R.id.rgPeakOrValley)).getCheckedRadioButtonId() != R.id.rbPeakOrValley_Peak;
        List<Integer> listPeakPos = new ArrayList<>();
        getPeakPos(data, listPeakPos, bValley, mStep);
        if (listPeakPos.size() != 2)
            return -1;
        int average = GetAverage(data, listPeakPos.get(0), listPeakPos.get(1), mStep);

        SendDispMessage("gain " + gain + " amplify " + amplify + " 最大值 " + (max - average));
        return max - average;
    }

    //设置LED，读峰值为MAX_PEAK
    class SetupLEDThread extends Thread {
        @Override
        public void run() {
//            int peak0 = 0, peak1 = 0;
            getStartStop();
            saveSettings();

//            for (amplify1 = 50; amplify1 > 0; amplify1--) {
//                if (amplify1 != 50) {
//                    try {
//                        Thread.sleep(5000);
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                }
//                peak1 = getMaxPeakSubMean(gain, amplify1);
//                if (peak1 == -1) {
//                    SendDispMessage("获取峰值失败");
//                    return;
//                }
//                if (peak1 < MAX_PEAK)
//                    break;
//                else peak0 = peak1;
//            }
            byte amplify1 = 1, amplify2 = 50;
            int peak1 = getMaxPeakSubMean(gain, amplify1);
            int peak2 = getMaxPeakSubMean(gain, amplify2);
            if (peak2 < MAX_PEAK) {
                amplify = amplify2;
            } else if (peak1 > MAX_PEAK) {
                amplify = amplify1;
            } else {
                while (amplify2 - amplify1 > 1) {
                    byte amplify = (byte) ((amplify1 + amplify2) / 2);
                    int peak = getMaxPeakSubMean(gain, amplify);
                    if (peak > MAX_PEAK) {
                        amplify2 = amplify;
                        peak2 = peak;
                    } else {
                        amplify1 = amplify;
                        peak1 = peak;
                    }
                }
                if (peak2 - MAX_PEAK < MAX_PEAK - peak1)
                    amplify = amplify2;
                else
                    amplify = amplify1;
            }

            SendDispMessage("gain: " + gain + " amplify: " + amplify);
            saveCalibration2Device();
        }
    }

    boolean saveCalibration2Device() {
        ParaScan para = new ParaScan();
        if(((RadioButton)findViewById(R.id.rbPeakOrValley_Peak)).isChecked()) {
            para.paraScanFluorescence.start = (byte) (mStart & 0xff);
            para.paraScanFluorescence.stop = (byte) (mStop & 0xff);
            para.paraScanFluorescence.gain = gain;
            para.paraScanFluorescence.amplify = amplify;
            para.paraScanFluorescence.color = testColor;
            para.bFluorescence=true;
            para.bColloidalGold=false;
        }else{
            para.paraScanColloidalGold.start = (byte) (mStart & 0xff);
            para.paraScanColloidalGold.stop = (byte) (mStop & 0xff);
            para.paraScanColloidalGold.gain = gain;
            para.paraScanColloidalGold.amplify = amplify;
            para.paraScanColloidalGold.color = testColor;
            para.bFluorescence=false;
            para.bColloidalGold=true;
        }
        if (!mScanTest.getDevice().saveParaScan2Device(para)) {
            SendDispMessage("保存校准值失败");
            return false;
        }
        SendDispMessage("保存校准值成功");
        return true;
    }

    boolean readCalibrationFromDevice() {
        ParaScan para = mScanTest.getDevice().readParaScanFromDevice();
        if (para == null)
            return false;
        int brightness=0;
        if(((RadioButton)findViewById(R.id.rbPeakOrValley_Peak)).isChecked()) {
            gain = para.paraScanFluorescence.gain;
            amplify = para.paraScanFluorescence.amplify;
            mStart = (para.paraScanFluorescence.start & 0xFF);
            mStop = (para.paraScanFluorescence.stop & 0xFF);
            color = para.paraScanFluorescence.color;
            brightness = para.paraScanFluorescence.getBrightness();
        }else{
            gain = para.paraScanColloidalGold.gain;
            amplify = para.paraScanColloidalGold.amplify;
            mStart = (para.paraScanColloidalGold.start & 0xFF);
            mStop = (para.paraScanColloidalGold.stop & 0xFF);
            color = para.paraScanColloidalGold.color;
            brightness = para.paraScanColloidalGold.getBrightness();
        }
        String strColor=Utils.byte2hexString(color);
        SendDispMessage("读设备校准值 亮度: " + brightness);
        mSBBrightness.setProgress(brightness);
        mEdtStart.setText(mStart + "");
        mEdtStop.setText(mStop + "");
        ((EditText) findViewById(R.id.edtColor)).setText(strColor);
        return true;
    }
}
